package com.dianpingmedia.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.dianpingmedia.simulate.model.DPPlanEntity;
import com.google.common.collect.Maps;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import com.google.protobuf.ByteString;
import net.logstash.logback.encoder.org.apache.commons.lang.ArrayUtils;
import net.logstash.logback.encoder.org.apache.commons.lang.StringUtils;
import org.assertj.core.util.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.management.VMManagement;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.security.MessageDigest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.zip.GZIPOutputStream;

/**
 * Created by Karl He on 2017-06-20.
 */
public class MiscUtil {

    private static Logger LOGGER = LoggerFactory.getLogger("MiscUtil");
    public static final String SETKEY_PREFIX = fromHex("EFBFBDEFBFBD00057400");//"\xac\xed\x00\x05t\x00";
    //    public static Gson gson = new Gson();
    public static Gson gson = new GsonBuilder()
            .disableHtmlEscaping()
            .create();
    public static AtomicLong atomicLong = new AtomicLong(System.currentTimeMillis());

    public static final int jvmPid() {
        try {
            RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
            Field jvm = runtime.getClass().getDeclaredField("jvm");
            jvm.setAccessible(true);
            VMManagement mgmt = (VMManagement) jvm.get(runtime);
            Method pidMethod = mgmt.getClass().getDeclaredMethod("getProcessId");
            pidMethod.setAccessible(true);
            int pid = (Integer) pidMethod.invoke(mgmt);
            return pid;
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * @param format 格式,如: yyyyMMdd yyMMdd yyyy-MM-dd
     * @return
     */
    public static String getDateString(String format) {
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);//获取年份
        int month = cal.get(Calendar.MONTH);//获取月份
        int day = cal.get(Calendar.DATE);//获取日

        if (format.equals("yyyyMMdd")) {
            return String.format("%d%02d%02d", year, month + 1, day);
        } else if (format.equals("yyMMdd")) {
            return String.format("%d%02d%02d", year % 100, month + 1, day);
        }

        return String.format("%d%-02d%-02d", year, month + 1, day);
    }

    /**
     * 获取年月日的数值
     *
     * @return yyyyMMdd
     */
    public static Long getDateLong() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String date = sdf.format(new Date());
        return Long.parseLong(date);
    }

    /**
     * 验证日期格式(yyyy-MM-dd或yyyyMMdd)
     *
     * @param str
     * @return
     */
    public static Boolean verifyDate(String str) {
        if (str == null) {
            return false;
        }

        if (str.length() != 8 && str.length() != 10) {
            return false;
        }

        if (str.length() == 8) {
            str = str.substring(0, 4) + "-" + str.substring(4, 6) + "-" + str.substring(6, 8);
        }

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            sdf.parse(str);
        } catch (ParseException e) {
            return false;
        }

        return true;
    }


    /**
     * 对字符串md5加密
     *
     * @param str
     * @return
     */
    public static String MD5(String str) {
        try {
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md.update(str.getBytes(Charset.forName("utf-8")));
            // digest()最后确定返回md5 hash值，返回值为8为字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
            return addPrefix(new BigInteger(1, md.digest()).toString(16).toUpperCase(), "0", 32);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    public static String rongyiMD5(String str) {
        System.err.println(str);


        try {

            String re = null;
            byte encrypt[];

            byte[] tem = str.getBytes();
            MessageDigest md5 = MessageDigest.getInstance("md5");
            md5.reset();
            md5.update(tem);
            encrypt = md5.digest();
            StringBuilder sb = new StringBuilder();
            for (byte t : encrypt) {
                String s = Integer.toHexString(t & 0xFF);
                if (s.length() == 1) {
                    s = "0" + s;
                }
                sb.append(s);
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 众盟数据签名
     *
     * @param paramMap
     * @return
     */
    public static String zmengSign(Map<String, Object> paramMap) {
        if (paramMap == null || paramMap.isEmpty()) {
            return "";
        }
        List<String> keys = Lists.newArrayList(paramMap.keySet());
        Collections.sort(keys);
        System.out.println("[zmengSign]keys:" + Arrays.toString(keys.toArray()));
        StringBuilder builder = new StringBuilder();
        for (String key : keys) {
            if (!key.equals("sign")) { //除了"sign"之外的参数都要参与签名
                if (paramMap.get(key) == null) {
                    continue;
                }
                String value = zmengSignFieldStr(key, paramMap.get(key));
                if (value != null) {
                    builder.append(key);
                    builder.append(value);
                }
            }
        }
        //做MD5加密生成签名
        System.out.println("[zmengSign]" + builder.toString());
        return MD5(builder.toString());
    }

    //签名
    public static String sign(JSONObject params) {

        Map<String, Object> paramMap = (Map) JSONObject.parse(params.toJSONString());
        List<String> keys = com.google.common.collect.Lists.newArrayList(paramMap.keySet());
        Collections.sort(keys);
        StringBuilder builder = new StringBuilder();
        for (String key : keys) {
            if ("sign".equals(key)) {
                continue;
            }
            builder.append(key);
            //字段值value转换成JSON串
            builder.append(JSON.toJSONString(paramMap.get(key)));
        }
        //做MD5加密生成签名
        return rongyiMD5(builder.toString()).toUpperCase();
    }

    /**
     * 字段值value转换成JSON串
     *
     * @param key
     * @param object
     * @return
     */
    public static String zmengSignFieldStr(String key, Object object) {
        if (object == null) {
            return null;
        }

        if (key.equals("id")) {
            return object.toString();//众盟的广告id,素材id为long型
        } else if (object.getClass().toString().toLowerCase().endsWith("map")) {
            try {
                Map<String, Object> map = ascendingMap(objToHash(object));
                return gson.toJson(map);
            } catch (Exception e) {
            }
            return null;
        } else if (object.getClass().toString().toLowerCase().endsWith("list")) {
            List<Object> objects = (List<Object>) object;
            if (objects.size() > 0) {
                String type = objects.get(0).getClass().toString();//class com.dianpingmedia.planentry.model.MaterialEntity
                if (type.toLowerCase().endsWith("map") || type.endsWith("MaterialEntity")) {
                    List list = new ArrayList<>();
                    for (Iterator it = objects.iterator(); it.hasNext(); ) {
                        Map map = jsonToMap(gson.toJson(it.next()));
                        list.add(ascendingMap(map));
                    }
                    return gson.toJson(list);
                }
            }
        }

        return gson.toJson(object);

    }


    public static String zmengSign(Object object) {
        try {
            return zmengSign(objToHash(object));
        } catch (IllegalArgumentException | IllegalAccessException e) {
            return null;
        }
    }

    /**
     * 对map进行顺序排列
     *
     * @param map
     * @return
     */
    public static Map<String, Object> ascendingMap(Map<String, Object> map) {
        List<Map.Entry<String, Object>> list = new LinkedList<Map.Entry<String, Object>>(map.entrySet());

        Collections.sort(list, new Comparator<Map.Entry<String, Object>>() {
            @Override
            public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
                return (o1.getKey()).compareTo(o2.getKey());
            }
        });
        Map<String, Object> result = new LinkedHashMap<>();
        for (Map.Entry<String, Object> entry : list) {
            result.put(entry.getKey(), entry.getValue());
        }

        if (result.containsKey("id")) {
            result.put("id", Long.valueOf(result.get("id").toString()));
        }

        return result;
    }


    public static String iFlySign(Object object, String iFlySecret) {
        try {

            Map<String, Object> map = GsonUtil.fromJson(MiscUtil.gson.toJson(object), new TypeToken<Map<String, Object>>() {
            });

            return iFlySign(map, iFlySecret);//iFlySign(objToHash(object)); //gson转换integer会变成double
        } catch (IllegalArgumentException e) //| IllegalAccessException e
        {
            return null;
        }
    }


    /**
     * 讯飞数据签名(素材导入/素材审核结果回复)
     *
     * @param map
     * @return
     */
    public static String iFlySign(Map<String, Object> map, String iFlySecret) {
        if (map == null || map.isEmpty()) {
            return "";
        }
        List<String> keys = Lists.newArrayList(map.keySet());
        Collections.sort(keys);
        System.out.println(Arrays.toString(keys.toArray()));

        StringBuilder builder = new StringBuilder();
        builder.append(iFlySecret);

        for (String key : keys) {
            if (!key.equals("sign")) { //除了"sign"之外的参数都要参与签名
                if (map.get(key) == null) {
                    continue;
                }
                Object value = map.get(key);
                builder.append(MiscUtil.gson.toJson(value));
            }
        }

        String connStr = builder.toString();
        System.out.println("sign data:" + connStr);

        return MD5(connStr);
    }


    public static String iFlySign(Map<String, Object> map) {
        StringBuilder paraSb = new StringBuilder("ssp_id=")
                .append(map.get("ssp_id"))
                .append("&")
                .append("time=")
                .append(map.get("time"))
                .append(map.get("token"));
        System.out.println(paraSb.toString());
        try {
            String str=paraSb.toString();
            byte encrypt[];

            byte[] tem = str.getBytes();
            MessageDigest md5 = MessageDigest.getInstance("md5");
            md5.reset();
            md5.update(tem);
            encrypt = md5.digest();
            StringBuilder sb = new StringBuilder();
            for (byte t : encrypt) {
                String s = Integer.toHexString(t & 0xFF);
                if (s.length() == 1) {
                    s = "0" + s;
                }
                sb.append(s);
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 讯飞POST数据附加信息(包括签名)
     *
     * @param map
     * @return
     */
    public static void iFlyAdditionalData(Map<String, Object> map, String iFlySspId, String iFlyToken, String iFlySecret) {
        if (map == null) {
            return;
        }
        map.put("sspId", iFlySspId);
        map.put("token", iFlyToken);
        String sign = iFlySign(map, iFlySecret);
        if (map.containsKey("sign")) {
            map.replace("sign", sign);
        } else {
            map.put("sign", sign);
        }
    }


    /**
     * 讯飞数据签名(媒体位广告位数据)
     * @param map
     * @return
     */
   /* public static String iFlyMediaSign(Map<String, Object> map) {9
        if (map == null) {
            return "";
        }
        if(!map.containsKey("ssp_id"))
            map.put("ssp_id",PlanEntryApp.iFlySspId);
        if(!map.containsKey("token"))
            map.put("token",PlanEntryApp.iFlyToken);
        if(!map.containsKey("time"))
            map.put("time",String.valueOf(System.currentTimeMillis()/1000));

        List<String> keys = Lists.newArrayList(map.keySet());
        Collections.sort(keys);
        StringBuilder builder = new StringBuilder();

        for (String key : keys) {
            if(!key.equals("sign") && !key.equals("token")) {
                Object value = map.get(key);
                if(builder.toString().length() > 0)
                    builder.append("&");
                builder.append(key);
                builder.append("=");
                builder.append(value);
            }
        }
        builder.append(PlanEntryApp.iFlyToken);

        String sign = MD5(builder.toString()).toLowerCase();
        map.put("sign", sign);

        return sign;
    }*/

    /**
     * url路径组合起来
     *
     * @param prefix
     * @param suffix
     * @return
     */
    public static String combineUrl(String prefix, String suffix) {
        /*if(prefix == null && suffix==null)
            return null;
        else if(prefix == null)
            return suffix;
        else if(suffix == null)
            return prefix;

        if(prefix.endsWith("/") && suffix.startsWith("/"))
            return prefix + suffix.substring(1);
        else if(prefix.endsWith("/") || suffix.startsWith("/"))
            return prefix + suffix;

        return prefix + "/" + suffix;*/
        return combineUrl(prefix, null, suffix);
    }

    public static String combineUrl(String prefix, String middle, String suffix) {
        if (prefix == null && middle == null && suffix == null) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        if (prefix != null) {
            sb.append(prefix);
            if (!prefix.endsWith("/") && (middle != null || suffix != null)) {
                sb.append("/");
            }
        }

        if (middle != null) {
            if (middle.startsWith("/")) {
                sb.append(middle.substring(1));
            } else {
                sb.append(middle);
            }
            if (!middle.endsWith("/") && suffix != null) {
                sb.append("/");
            }
        }

        if (suffix != null) {
            if (suffix.startsWith("/")) {
                sb.append(suffix.substring(1));
            } else {
                sb.append(suffix);
            }
        }

        return sb.toString();
    }

    public static String addPrefix(String str, String prefix, int strLength) {
        int needLength = strLength - str.length();
        if (needLength > 0) {
            StringBuffer sb = new StringBuffer();
            while (needLength-- > 0) {
                sb.append(prefix);
            }
            sb.append(str);// 左补
            return sb.toString();
        }

        return str;
    }

    public static String addSuffix(String str, String suffix, int strLength) {
        int needLength = strLength - str.length();
        if (needLength > 0) {
            StringBuffer sb = new StringBuffer();
            sb.append(str);// 右边
            while (needLength-- > 0) {
                sb.append(suffix);
            }
            return sb.toString();
        }

        return str;
    }

    /**
     * 将java实体bean转换成hashmap, java反射将实例化的实体bean转换成hashmap<成员变量名称,实例化后的成员变量的值>
     *
     * @param obj
     * @return
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     */
    public static HashMap<String, Object> objToHash(Object obj) throws IllegalArgumentException, IllegalAccessException {

        HashMap<String, Object> hashMap = new HashMap<String, Object>();
        Class clazz = obj.getClass();
        List<Class> clazzs = new ArrayList<Class>();

        do {
            clazzs.add(clazz);
            clazz = clazz.getSuperclass();
        } while (!clazz.equals(Object.class));

        for (Class iClazz : clazzs) {
            Field[] fields = iClazz.getDeclaredFields();
            for (Field field : fields) {
                Object objVal = null;
                field.setAccessible(true);
                objVal = field.get(obj);
                hashMap.put(field.getName(), objVal);
            }
        }

        return hashMap;
    }

    public static Map<String, Object> obj2Map(Object obj) {
        Map<String, Object> map = new HashMap<>();
        try {
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                map.put(field.getName(), field.get(obj));
            }
        } catch (Exception e) {
        }
        return map;
    }


    /**
     * 把json字符串转换为map请使用此方法,如果用gson转换的话Integer会变成Double
     */
    public static Map<String, Object> jsonToMap(String json) {
        return GsonUtil.fromJson(json, new TypeToken<Map<String, Object>>() {
        });
    }

    public static Object map2Obj(Map<String, Object> map, Class<?> clz) {
        Object obj = null;
        try {
            obj = clz.newInstance();
            Field[] declaredFields = obj.getClass().getDeclaredFields();
            for (Field field : declaredFields) {
                int mod = field.getModifiers();
                if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
                    continue;
                }
                field.setAccessible(true);
                field.set(obj, map.get(field.getName()));
            }
        } catch (Exception e) {
        }
        return obj;
    }

    public static List<Integer> getMediaProviderIdList(String[] positionList) {
        if (positionList.length == 0) {
            return null;
        }

        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < positionList.length; i++) {
            if (positionList[i].length() > 4) {
                Integer prefix = Integer.parseInt(positionList[i].substring(0, 4));
                boolean found = false;
                for (Integer item : list) {
                    if (item.equals(prefix)) {
                        found = true;
                        break;
                    }
                }

                if (!found) {
                    list.add(prefix);
                }
            }
        }

        return list;
    }

    public static String inputStreamToString(InputStream is) {

        String line;
        StringBuilder total = new StringBuilder();

        try {

            // Wrap a BufferedReader around the InputStream
            BufferedReader rd = new BufferedReader(new InputStreamReader(is, "utf-8"));

            // Read response until the end
            while ((line = rd.readLine()) != null) {
                total.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Return full string
        return total.toString();
    }

    /**
     * 获取令牌
     *
     * @param request
     * @return
     */
    public static String getToken(HttpServletRequest request) {
        String token = request.getParameter("token");
        if (token != null) {
            return token;
        }

        String authentication = request.getHeader("Authorization");

        if (authentication != null) {
            if (authentication.startsWith("Bearer")) {
                token = authentication.substring(6).trim();
            }
        }

        return token;
    }

    public static Map<String, Object> tokenBodyMap(String token) {
        if (token != null) {
            int pos1 = token.indexOf('.');
            int pos2 = token.indexOf('.', pos1 + 1);
            if (pos1 > 0 && pos2 > pos1) {
                String body = token.substring(pos1 + 1, pos2);
                body = new String(Base64.getDecoder().decode(body));
                return MiscUtil.jsonToMap(body);
            }
        }

        return null;
    }

    public static String getMapString(Map<String, Object> map, String key) {
        if (map != null) {
            if (map.containsKey(key)) {
                return map.get(key).toString();
            }
        }

        return "";
    }

    public static Object getMapObject(Map<String, Object> map, String key) {
        if (map != null) {
            if (map.containsKey(key)) {
                return map.get(key);
            }
        }

        return null;
    }


    public static String getDefaultCharSet() {
        OutputStreamWriter writer = new OutputStreamWriter(new ByteArrayOutputStream());
        String enc = writer.getEncoding();
        try {
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return enc;
    }

    /**
     * redis的Key值如果有\xac\xed\x00\x05t\x00\x**开头的去掉它,默认编码下的值为0xEF 0xBF 0xBD 0xEF 0xBF 0xBD 0x00 0x05 0x74 0x00 0x** (**是Key的长度)
     *
     * @param key
     * @return
     */
    public static String removeRedisPrefix(String key) {
        if (key.startsWith(SETKEY_PREFIX)) {
            return key.substring(SETKEY_PREFIX.length() + 1);
        }

        return key;
    }


    private static final String HEXSTRING = "0123456789ABCDEF";

    /**
     * 将字符串编码成16进制数字
     *
     * @param str ASCII字符串,如"KAEL"
     * @return
     */
    public static String toHex(String str) {
        byte[] bytes = str.getBytes();//根据默认编码获取字节数组
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        // 将字节数组中每个字节拆解成2位16进制整数
        for (int i = 0; i < bytes.length; i++) {
            sb.append(HEXSTRING.charAt((bytes[i] & 0xf0) >> 4));
            sb.append(HEXSTRING.charAt((bytes[i] & 0x0f) >> 0));
        }
        return sb.toString();
    }


    /**
     * 将16进制数字解码成字符串
     *
     * @param bytes 16进制的字符串,如"314B5206"
     * @return
     */
    public static String fromHex(String bytes) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length() / 2);
        // 将每2位16进制整数组装成一个字节
        for (int i = 0; i < bytes.length(); i += 2) {
            baos.write((HEXSTRING.indexOf(bytes.charAt(i)) << 4 | HEXSTRING
                    .indexOf(bytes.charAt(i + 1))));
        }
        return new String(baos.toByteArray());
    }


    public static <T> ArrayList<T> fromJsonList(String json, Class<T> cls) {
        ArrayList<T> list = new ArrayList<T>();
        JsonArray array = new JsonParser().parse(json).getAsJsonArray();
        for (final JsonElement elem : array) {
            list.add(gson.fromJson(elem, cls));
        }
        return list;
    }

    public static String getString(Object obj) {
        if (obj == null) {
            return null;
        }

        return obj.toString();
    }

    public static boolean isEmpty(String str) {
        if (str == null) {
            return true;
        }

        str = str.trim();

        return str.isEmpty();
    }

    public static String encodeUrl(String url) {
        try {
            return URLEncoder.encode(url, "UTF-8");
        } catch (Exception e) {

        }

        return url;
    }

    /**
     * @param date   默认当前
     * @param format 格式,如: yyyyMMdd yyMMdd yyyy-MM-dd(default)
     * @return
     */
    public static String formatDate(Date date, String format) {
        if (date == null) {
            date = new Date();
        }
        if (format == null) {
            format = "yyyy-MM-dd";
        }

        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int year = cal.get(Calendar.YEAR);//获取年份
        int month = cal.get(Calendar.MONTH);//获取月份
        int day = cal.get(Calendar.DATE);//获取日

        if (format.equals("yyyyMMdd")) {
            return String.format("%d%02d%02d", year, month + 1, day);
        } else if (format.equals("yyMMdd")) {
            return String.format("%d%02d%02d", year % 100, month + 1, day);
        }

        return String.format("%d-%02d-%02d", year, month + 1, day);
    }

    public static String formatCalendar(Calendar calendar, String format) {
        if (format == null) {
            format = "yyyy-MM-dd";
        }

        int year = calendar.get(Calendar.YEAR);//获取年份
        int month = calendar.get(Calendar.MONTH);//获取月份
        int day = calendar.get(Calendar.DATE);//获取日

        if (format.equals("yyyyMMdd")) {
            return String.format("%d%02d%02d", year, month + 1, day);
        } else if (format.equals("yyMMdd")) {
            return String.format("%d%02d%02d", year % 100, month + 1, day);
        }

        return String.format("%d%-02d%-02d", year, month + 1, day);
    }

    /**
     * 获取日期
     *
     * @param date 原日期
     * @param days 变化的天数
     * @return
     */
    public static Date getOffsetDate(Date date, Integer days) {
        if (date == null) {
            date = new Date();
        }

        if (days == null) {
            days = 0;
        }

        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, days);//把日期往后增加一天.整数往后推,负数往前移动
        return calendar.getTime(); //这个时间就是日期往后推一天的结果
    }

    /**
     * @param bytes
     * @return
     */
    public static byte[] base64Decode(final byte[] bytes) {
        return Base64.getDecoder().decode(bytes);
    }

    /**
     * 二进制数据编码为BASE64字符串
     *
     * @param bytes
     * @return
     * @throws Exception
     */
    public static String base64Encode(final byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }


    /**
     * GZip压缩
     *
     * @param bytes
     * @return
     */
    public static byte[] compress(byte[] bytes) {
        try {
            ByteArrayOutputStream originalContent = new ByteArrayOutputStream();
            originalContent.write(bytes);

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            GZIPOutputStream gzipOut = new GZIPOutputStream(baos);
            originalContent.writeTo(gzipOut);
            gzipOut.finish();

            return baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static String getZMErrorMsg(Integer errorCode) {
        if (errorCode.equals(0)) {
            return "有广告返回";
        } else if (errorCode.equals(101)) {
            return "requestId格式不对";
        } else if (errorCode.equals(102)) {
            return "没有对应尺寸广告位";
        } else if (errorCode.equals(103)) {
            return "屏设备没有备案";
        } else if (errorCode.equals(201)) {
            return "广告主没有出价";
        } else if (errorCode.equals(202)) {
            return "没有匹配的广告";
        } else if (errorCode.equals(203)) {
            return "广告响应适配失败";
        } else if (errorCode.equals(204)) {
            return "无广告";
        } else if (errorCode.equals(500)) {
            return "系统内部异常";
        } else {
            return "位置错误";
        }
    }

    public static boolean downloadFileDirect(HttpServletRequest request, HttpServletResponse response, String filePath) {
        boolean bOK = false;
        File file = new File(filePath);
        FileInputStream fis;
        try {
            fis = new FileInputStream(file);
        } catch (FileNotFoundException e1) {
            return false;
        }

        long fileSize = file.length();//fis.available();

        //读取文件上传到服务器
        response.addHeader("Content-Disposition", "attachment;filename=" + getFileName(filePath));
        response.addHeader("Content-Length", "" + fileSize);
        response.addHeader("Content-Transfer-Encoding", "binary");
        response.addHeader("ContentType", "application/octet-stream");


        int numReadByte = 0;
        int sendCount = 0;
        byte[] bytes = new byte[1024];
        try {
            while ((numReadByte = fis.read(bytes, 0, 1024)) > 0) {
                //* 第一种方式,直接发送流 out.print(MiscFuns.bytesToChars(bytes, 0, numReadByte)); //out.write(bytes, 0, numReadByte);//
                response.getOutputStream().write(bytes, 0, numReadByte);
                sendCount += numReadByte;
            }

            if (fileSize == sendCount) {
                bOK = true;
            }
        } catch (Exception e) {
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                    fis = null;
                }
            } catch (Exception e) {
            }
        }

        return bOK;
    }

    public static String getFileName(String fullName) {//c:\temp\2016\M09\D14\1620649381658.MP4
        for (int i = fullName.length() - 1; i >= 0; i--) {
            if (fullName.substring(i, i + 1).equals("\\") || fullName.substring(i, i + 1).equals("/")) {
                return fullName.substring(i + 1);
            }
        }

        return fullName;
    }

    /*
     * 获取文件路径(包含斜杠)
     */
    public static String getFilePath(String fullName) {//c:\temp\2016\M09\D14\1620649381658.MP4
        for (int i = fullName.length() - 1; i >= 0; i--) {
            if (fullName.substring(i, i + 1).equals("\\") || fullName.substring(i, i + 1).equals("/")) {
                return fullName.substring(0, i + 1);
            }
        }

        return fullName;
    }

    public static String getHeaderItem(HttpServletRequest request, String key) {
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            if (headerNames.nextElement().toString().toLowerCase().equals(key.toLowerCase())) {
                return request.getHeader(key).trim();
            }
        }

        return null;
    }

    public static void closeInputStream(InputStream is, DataInputStream dis) {
        try {
            if (dis != null) {
                dis.close();
            }
            if (is != null) {
                is.close();
            }
        } catch (Exception e2) {
        }
    }


    public static String bytesToString(ByteString src, String charSet) {
        if (StringUtils.isEmpty(charSet)) {
            charSet = "utf8";
        }
        return bytesToString(src.toByteArray(), charSet);
    }

    public static String bytesToString(byte[] input, String charSet) {

        if (ArrayUtils.isEmpty(input)) {
            return StringUtils.EMPTY;
        }

        ByteBuffer buffer = ByteBuffer.allocate(input.length);
        buffer.put(input);
        buffer.flip();

        Charset charset = null;
        CharsetDecoder decoder = null;
        CharBuffer charBuffer = null;

        try {
            charset = Charset.forName(charSet);
            decoder = charset.newDecoder();
            charBuffer = decoder.decode(buffer.asReadOnlyBuffer());

            return charBuffer.toString();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }


    public static String getNextYearNowDate() {
        String format = "yyyy-MM-dd";
        Date date = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int year = cal.get(Calendar.YEAR) + 1;//获取年份
        int month = cal.get(Calendar.MONTH);//获取月份
        int day = cal.get(Calendar.DATE);//获取日
        return String.format("%d-%02d-%02d", year, month + 1, day);
    }


    public static String dateToStamp(String s) throws Exception {
        String res = null;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = simpleDateFormat.parse(s);
        long ts = date.getTime();
        res = String.valueOf(ts);
        return res;
    }


    public static String rongyiSign(DPPlanEntity DPPlanEntity) {
        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSON(DPPlanEntity).toString());
        Map<String, Object> paramMap = (Map) JSONObject.parse(jsonObject.toJSONString());
        List<String> keys = Lists.newArrayList(paramMap.keySet());
        Collections.sort(keys);
        StringBuilder builder = new StringBuilder();
        for (String key : keys) {
            if ("sign".equals(key)) {
                continue;
            }
            builder.append(key);
            builder.append(JSON.toJSONString(paramMap.get(key)));
        }
        System.out.println("[rongyi]:" + builder.toString());
        return MD5(builder.toString());
    }


    public static Map<String, Object> decodeToken(String token, String decoderTokenSecret) {
        Map<String, Object> map = new HashMap<>();
        try {
            Algorithm algorithm = Algorithm.HMAC256(decoderTokenSecret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("DIANPING OOH@X2.0")
                    .build(); //Reusable verifier instance

            DecodedJWT jwt = verifier.verify(token);
            if (jwt != null) {
                Map<String, Claim> mapClain = jwt.getClaims();

                Set<String> set = mapClain.keySet();
                for (String key : set) {
                    if (key.equals("cid")) {
                        map.put("customerId", mapClain.get(key).asInt());
                    } else if (key.equals("uid")) {
                        map.put("userId", mapClain.get(key).asInt());
                    } else if (key.equals("type")) {
                        map.put("loginType", mapClain.get(key).asInt());
                    } else if (key.equals("role")) {
                        map.put("role", mapClain.get(key).asString());
                    } else if (key.equals("username")) {
                        map.put("username", mapClain.get(key).asString());
                    } else if (key.equals("gid")) {
                        map.put("groupId", mapClain.get(key).asInt());

                    }
                }
            }
        } catch (UnsupportedEncodingException exception) {
            //UTF-8 encoding not supported
            LOGGER.info("Encoding not supported");
        } catch (JWTVerificationException exception) {
            //Invalid signature/claims
            LOGGER.info("无效签名"); //Invalid signature/claims
        } catch (Exception e) {

            LOGGER.info("decoder token Fail: " + e.getMessage());
        }
        LOGGER.info("decoder token Success: " + MiscUtil.gson.toJson(map));
        return map;
    }


//    public static void saveThreePartyAdRequestError(String msg,Integer dspId) {
//        FileWriter fw = null;
//        try {
//            // 如果文件存在，则追加内容；如果文件不存在，则创建文件
//            File directory = new File("");// 参数为空
//            String courseFile = directory.getCanonicalPath();
//            System.out.println(courseFile);
//            File f = new File(courseFile);
//            fw = new FileWriter(f, true);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        PrintWriter pw = new PrintWriter(fw);
//        pw.println(msg);
//        pw.flush();
//        try {
//            fw.flush();
//            pw.close();
//            fw.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }


}
